Obsidian 実行中タスク選択4
2024/10/24
ソート(時刻つきの場合はセクションを跨いでソート、時刻なしの場合はもとのセクションの末尾に移動)
実行中タスク選択
code:js
<%*
// ===== 今日日付のファイルを開く =====
// 今日の日付をフォーマットして返す関数 (例: "2024-10-24")
function getTodayDate() {
const today = new Date();
const year = today.getFullYear();
const month = String(today.getMonth() + 1).padStart(2, '0');
const day = String(today.getDate()).padStart(2, '0');
return ${year}-${month}-${day};
}
// 今日日付のデイリーノートを開く関数
async function openTodayDailyNote() {
const todayDate = getTodayDate();
const fileName = ${todayDate}.md; // デイリーノートのファイル名を生成
const dailyNotesFolder = 'notes'; // デイリーノートのフォルダパス(必要に応じて変更)
// 現在開いているノートを確認
const currentFile = this.app.workspace.getActiveFile();
if (currentFile) {
const currentFileName = currentFile.basename;
// 現在開いているノートが今日のデイリーノートであれば、何もしない
if (currentFileName === todayDate) {
// console.log('今日日付のデイリーノートを既に開いています');
return;
}
}
// 今日日付のデイリーノートを開く
const todayFilePath = ${dailyNotesFolder}/${fileName};
const fileExists = await this.app.vault.adapter.exists(todayFilePath);
if (fileExists) {
// ノートが既に存在する場合、開く
const todayFile = await this.app.vault.getAbstractFileByPath(todayFilePath);
this.app.workspace.activeLeaf.openFile(todayFile);
} else {
// ノートが存在しない場合、作成して開く
const todayFile = await this.app.vault.create(todayFilePath, # ${todayDate}\n);
this.app.workspace.activeLeaf.openFile(todayFile);
}
}
// コードを実行
openTodayDailyNote();
// ===== ソート + 未完了タスク選択 =====
function sortTasksByTime() {
const activeFile = app.workspace.getActiveFile();
if (!activeFile) {
new Notice('ファイルが開かれていません');
return;
}
// ユーザーのテキストを取得
app.vault.read(activeFile).then(text => {
// 行ごとに分割
const lines = text.split("\n");
// セクション区切りの検出パターン("### 🗂️"で始まる行)
const sectionDelimiter = /^### 🗂️/;
// 時刻を含む行を検出するパターン(@HH:MM形式の時刻は除外)
const timePattern = /(?<!@)\b\d{1,2}:\d{2}\b/;
let sections = [];
let currentSection = { header: null, linesWithTime: [], linesWithoutTime: [] };
let beforeFirstSection = [];
let sectionMap = {}; // 時刻なし行とセクションのマッピング
// フラグ:最初のセクションが見つかったか
let foundFirstSection = false;
// 行をループしてセクションごとにまとめる
lines.forEach(line => {
if (sectionDelimiter.test(line)) {
foundFirstSection = true;
// 新しいセクションが始まる場合、前のセクションを保存
if (currentSection.header !== null) {
sections.push(currentSection);
}
// 新しいセクション開始
currentSection = { header: line, linesWithTime: [], linesWithoutTime: [] };
} else if (foundFirstSection) {
// 時刻があるかないかで分類
if (timePattern.test(line)) {
currentSection.linesWithTime.push(line);
} else {
currentSection.linesWithoutTime.push(line);
// マッピングに追加(時刻なし行をセクションに紐付け)
}
}
} else {
// 最初のセクションより前の行をそのまま保持
beforeFirstSection.push(line);
}
});
// 最後のセクションを保存
if (currentSection.header !== null) {
sections.push(currentSection);
}
// セクションと時刻ありの行をすべて集めて一つのリストに
let allItemsWithTime = [];
sections.forEach(section => {
if (timePattern.test(section.header)) {
allItemsWithTime.push({ line: section.header, isHeader: true });
}
section.linesWithTime.forEach(line => {
allItemsWithTime.push({ line: line, isHeader: false });
});
});
// 全ての時刻あり項目を時刻順にソート
allItemsWithTime.sort((a, b) => {
const timeA = a.line.match(timePattern)0; const timeB = b.line.match(timePattern)0; return timeA.localeCompare(timeB);
});
// ソート結果をセクションごとに整理して保持
let sortedSections = [];
let currentSortedSection = null;
allItemsWithTime.forEach(item => {
if (item.isHeader) {
// 新しいセクションが開始
if (currentSortedSection !== null) {
sortedSections.push(currentSortedSection);
}
currentSortedSection = { header: item.line, lines: [] };
} else {
// セクションに時刻あり行を追加
if (currentSortedSection !== null) {
currentSortedSection.lines.push(item.line);
}
}
});
// 最後のセクションも追加
if (currentSortedSection !== null) {
sortedSections.push(currentSortedSection);
}
// 時刻なしの行を、元のセクションに基づいて追加
sortedSections.forEach(section => {
const header = section.header;
// マッピングに基づいて、時刻なしの行をセクションの末尾に追加
section.lines.push(...sectionMapheader); }
});
// セクションごとのリストを結合して元のノートに戻す
sortedSections.forEach(section => {
result.push(section.header);
result.push(...section.lines);
});
// 結果をテキストに戻してノートに保存
app.vault.modify(activeFile, result.join("\n")).then(() => {
// ===== カーソルを未完了のチェックボックスに合わせる =====
// エディタ内で未完了タスクを探し、カーソルをその行末に移動する関数
function moveToFirstIncompleteTask() {
const editor = this.app.workspace.activeLeaf.view.sourceMode.cmEditor;
const doc = editor.getDoc();
const lines = doc.lineCount(); // ドキュメント内の行数を取得
// 全行をループして未完了タスクを探す
for (let i = 0; i < lines; i++) {
const lineText = doc.getLine(i); // 現在の行のテキストを取得
// 未完了タスクを判定(- で始まる行を探す)
if (lineText.startsWith('- ')) {
// タスクが見つかった場合、その行末にカーソルを移動
const lineEnd = lineText.length; // 行の末尾の位置
doc.setCursor({ line: i, ch: lineEnd }); // カーソルを行末に設定
return; // 最初の未完了タスクを見つけたら終了
}
}
// 未完了タスクが見つからなかった場合の処理(必要であれば)
console.log("未完了タスクが見つかりませんでした");
}
// コードを実行
moveToFirstIncompleteTask();
});
});
}
// 関数を実行
sortTasksByTime();
%>